package confs;
import java.util.ArrayList;
import java.util.Arrays;
import org.omg.IOP.Codec;


/**
*@author tonychao 
*单个参数的值和属性
*
*/

//import com.sun.jersey.core.impl.provider.xml.ThreadLocalSingletonContextProvider;

import confs.DataType;

public class SingleParameter implements Cloneable{
	//一定被赋值

	public DataType.typeProperty typeProperty =null; //指明该值的数据类型
	public String name; //参数名称
	public int value; //存贮数据的值 int or string , double 型的数据实际上精确到两位小数点，以int型存贮 有枚举型的变量是使用String 进行存储，但是下标使用value进行记录
	public int defaultValue;
	private ArrayList<String> code ;
	public String description;
	
	/*
	 * 常规属性的赋值(数值型-整数)
	 * */
	public SingleParameter (String name, String confstr_default_value,DataType.typeProperty type,String description) {
		this.name= name;
		this.typeProperty=type;
		this.value =toValue(confstr_default_value); //这个函数必须最后才能调用
		this.defaultValue=toValue(confstr_default_value);
		this.description=description;
	}
	
	

	/*
	 * 枚举型的赋值
	 * */
	public SingleParameter(String name,String[] valueList,DataType.typeProperty type,String description){ 
		this.name= name;
		this.typeProperty=type;
		this.code=new ArrayList<String>(Arrays.asList(valueList)) ;
		this.value =toValue(valueList[0]);//这个函数必须最后才能调用
		this.defaultValue=toValue(valueList[0]);
		this.description=description;
	}
	

 public SingleParameter clone() {  
    	SingleParameter ret = null;  
        try{  
            ret = (SingleParameter)super.clone();  
        }catch(CloneNotSupportedException e) {  
            e.printStackTrace();  
        }  
        return ret;  
    }  

	
	//用于返回该值的String型的值如“10m”
	@Override
	public String toString() {
		String ret="";
		// 以int型存储的数据
		switch (this.name){
			// 空间 mb int 型
			case "spark.broadcast.blockSize" :
			case "spark.driver.memory" :
			case "spark.executor.memory":
			case "spark.reducer.maxSizeInFlight":
			case "spark.driver.maxResultSize":
				ret = String.valueOf(this.value)+"m";
				break;
			case "spark.shuffle.file.buffer":
				ret = String.valueOf(this.value)+"k";
				break;
			// true、false
			case "spark.broadcast.compress":
			case "spark.shuffle.compress":
			case "spark.shuffle.spill.compress":
			case "spark.rdd.compress":
				ret=this.value==1?"TRUE":"FALSE";
				break;
				//比例
			case "spark.memory.fraction":
			case "spark.memory.storageFraction":
				ret = String.valueOf(0.01*this.value);
				if (ret.length()>=4){
					ret=ret.substring(0, 4);
				}
				//System.err.println(ret);
				break;
				//编码
			case "spark.io.compression.codec":
				ret=this.code.get(this.value);
				break;
			//不动
			case "spark.default.parallelism":
			case "spark.driver.cores":
			case "spark.task.cpus":
			case "spark.executor.cores":
			case "spark.rpc.message.maxSize":
				ret= String.valueOf(this.value);
				break;
			default:
				System.err.println("没有找到参数"+this.name+"对应的字符串表示形式");
				return null;
		}
		return ret;
	}
	
	
	
	/*
	 * 用于为每一个输入的参数，根据其类别对其进行赋值，但是目前为了方便，只对ISChosen的 参数进行这种转换
	 * 这个函数必须在对象构造的最后才能调用
	 */
	 public int toValue(String confstr){
		// System.out.println("DEBUG:"+this.name);

			 if (confstr.equals(""))  this.value= -1;  //表示默认值是不存在的
			 
			 //内存
			 else if(confstr.matches("^\\d+[mMgGkK]$")&&this.typeProperty.equals(DataType.typeProperty.INT)){
				 //解析 conf中的字符串为 MB形式，并且直接只输出数字
				String tmp=confstr.substring(0, confstr.length()-1);//去尾 nNmM 正则表达式由于使用字符串·所以还是要使用两个反斜杠
				if(confstr.matches("^\\d+[mM]")){
					 this.value= Integer.parseInt(tmp);
				}
				else if(confstr.matches("^\\d+[gG]")){
					 this.value= 1024*Integer.parseInt(tmp);
				}
				else if(confstr.matches("^\\d+[kK]")){
					 this.value= Integer.parseInt(tmp);
				}
				else {
					 System.err.println("SingleParameter未经解析的参数属性值");
					 System.exit(1);
				}
			 }
			 
			 //INT数字
			 else if (confstr.matches("^\\d+$")&&this.typeProperty.equals(DataType.typeProperty.INT)){
				 this.value=Integer.parseInt(confstr);
			 }
			 
			 //比例
			 else if(confstr.matches("\\d+\\.\\d+")&&this.typeProperty.equals(DataType.typeProperty.DOUBLE)){
				 Double doubleValue=Double.valueOf(confstr);
				 this.value= (int)(100*doubleValue);
			 }
			 
			 //布尔
			 else if ((confstr.toLowerCase().equals("true")||confstr.toLowerCase().equals("false"))&&this.typeProperty.equals(DataType.typeProperty.BOOLEAN)){
				 String tmp =confstr.toLowerCase();//   TRUE　FLASE true false
				 if(tmp.equals("true")) this.value=1;
				 else this.value=0;

				// file.add(String.valueOf(parseConfIntoBoolean(confstr)?1:0));
			}
			 //类别属性
			 else if(this.typeProperty.equals(DataType.typeProperty.CATEGORY_3)){
				 int tmp=this.code.indexOf(confstr);
				 this.value=tmp;
			}
			 
			 //其他,暂时报错
			 else{
				 System.err.println("SingleParameter未经解析的参数属性值");
				 System.exit(1);
			 }
			 return this.value;
		 }

	 
	
	 
	
}
